home *** CD-ROM | disk | FTP | other *** search
/ Floppyshop Select / Floppyshop - Select / Floppyshop - Select.iso / multitas.k / gluestik / gsdev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-02  |  9.1 KB  |  301 lines

  1. #include "kerbind.h"
  2. #include "gs_descr.h"
  3.  
  4. static long gssock_open(FILEPTR *fp);
  5. static long gssock_write(FILEPTR *fp, char *buf, long buflen);
  6. #if 0    /* This is not static anymore, so that gs_read_delim() can use it */
  7. static
  8. #endif
  9.        long gssock_read(FILEPTR *fp, char *buf, long buflen);
  10. static long gssock_lseek(FILEPTR *fp, long where, short whence);
  11. static long gssock_ioctl(FILEPTR *fp, short cmd, void *buf);
  12. static long gssock_datime(FILEPTR *fp, short *timeptr, short rwflag);
  13. static long gssock_close(FILEPTR *fp, short pid);
  14. static long gssock_select(FILEPTR *fp, long proc, short mode);
  15. static void gssock_unselect(FILEPTR *fp, long proc, short mode);
  16. static long gs_command(FILEPTR *fp, union GS_cmd *args);
  17.  
  18. struct devdrv gsdev = {
  19.   gssock_open, gssock_write, gssock_read, gssock_lseek,
  20.   gssock_ioctl, gssock_datime, gssock_close,
  21.   gssock_select, gssock_unselect,
  22.   { 0L, 0L, 0L }
  23. };
  24.  
  25. struct dev_descr gsdev_descr = {
  26.   &gsdev, 0, 0, (struct tty *)0, { 0L, 0L, 0L, 0L }
  27. };
  28.  
  29. static long gssock_open(FILEPTR *fp)
  30. {
  31.   struct GS *gs = gs_create();
  32.  
  33.   if (!gs) {
  34.     DEBUG(("gsdev: gssock_open: out of memory"));
  35.     LOG(DBG_ERROR, "gssock_open() returns %E", E_NOMEM);
  36.     return E_NOMEM;
  37.   }
  38.  
  39.   LOG(DBG_SYSCALL, "gssock_open() returns 0");
  40.   fp->devinfo = (long)gs;
  41.   return 0;
  42. }
  43.  
  44. static long gssock_write(FILEPTR *fp, char *buf, long buflen)
  45. {
  46.   struct GS *gs = (struct GS *)fp->devinfo;
  47.   long r, n;
  48.  
  49.   LOG(DBG_SYSCALL, "In gssock_write(%p, %p, %l)",
  50.       (void *)fp, (void *)buf, buflen);
  51.  
  52.   if (gs->flags & GS_NOSOCKET) {
  53.     LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): bad handle",
  54.     (void *)fp, (void *)buf, buflen);
  55.     return E_BADHANDLE;
  56.   }
  57.  
  58.   if ((gs->flags & GS_LISTENING) && gs_accept(gs) != 0) {
  59.     LOG(DBG_SYSCALL, "In gssock_write(%p, %p, %l): no connections arrived",
  60.     (void *)fp, (void *)buf, buflen);
  61.     return E_LISTEN;
  62.   }
  63.  
  64. #if 0
  65.   /* This is kind of a lie, but at least it's an error code a STiK app will
  66.    * be prepared to deal with. */
  67.   if ((gs->flags & GS_PEND_OPEN) && gs_establish(gs) != 0) {
  68.     LOG(DBG_SYSCALL, "In gssock_write(%p, %p, %l): open in progress",
  69.     (void *)fp, (void *)buf, buflen);
  70.     return E_OBUFFULL;
  71.   }
  72. #endif
  73.  
  74.   /* STiK has no provisions for writing part of a buffer and saving the
  75.    * rest for later; so make sure we can write the whole thing. */
  76.   r = f_cntl(gs->sock_fd, (long)&n, FIONWRITE);
  77.   if (r < 0) {
  78.     LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): Fcntl(FIONWRITE) returned %d",
  79.     (void *)fp, (void *)buf, buflen, r);
  80.     return gs_xlate_error(r, "gssock_write");
  81.   }
  82.   if (n < buflen) {
  83.     LOG(DBG_ERROR,
  84.     "In gssock_write(%p, %p, %l): can only write %l bytes; "
  85.     "returning E_OBUFFULL",
  86.     (void *)fp, (void *)buf, buflen, n);
  87.     return E_OBUFFULL;
  88.   }
  89.  
  90.   /* Okay, we can safely write. */
  91.   r = f_write(gs->sock_fd, buflen, buf);
  92.   if (r < 0) {
  93.     LOG(DBG_ERROR, "In gssock_write(%p, %p, %l): Fwrite() returned %e",
  94.     (void *)fp, (void *)buf, buflen, r);
  95.     return gs_xlate_error(r, "gssock_write");
  96.   } else {
  97.     /* Okay, according to the Fcntl(), we should have been able to write
  98.      * everything; warn if we didn't. */
  99.     if (r < buflen)
  100.       LOG(DBG_ERROR, "In gssock_write(%p, %p, %l):  "
  101.       "only got %l of %l bytes",
  102.       (void *)fp, (void *)buf, buflen, r, buflen);
  103.     LOG(DBG_SYSCALL, "gssock_write(%p, %p, %l) returns E_NORMAL",
  104.     (void *)fp, (void *)buf, buflen);
  105.     return E_NORMAL;
  106.   }
  107. }
  108.  
  109. long gssock_read(FILEPTR *fp, char *buf, long buflen)
  110. {
  111.   struct GS *gs = (struct GS *)fp->devinfo;
  112.   long r, n;
  113.  
  114.   LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l)",
  115.       (void *)fp, (void *)buf, buflen);
  116.  
  117.   if (gs->flags & GS_NOSOCKET) {
  118.     LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): bad handle",
  119.     (void *)fp, (void *)buf, buflen);
  120.     return E_BADHANDLE;
  121.   }
  122.  
  123.   if ((gs->flags & GS_LISTENING) && gs_accept(gs) != 0) {
  124.     LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): no connections arrived",
  125.     (void *)fp, (void *)buf, buflen);
  126.     return E_LISTEN;
  127.   }
  128.  
  129. #if 0
  130.   if ((gs->flags & GS_PEND_OPEN) && gs_establish(gs) != 0) {
  131.     LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): open in progress",
  132.     (void *)fp, (void *)buf, buflen);
  133.     return E_NODATA;
  134.   }
  135. #endif
  136.  
  137.   /* STiK has no provisions for reading less than a full buffer's worth of
  138.    * data; make sure we can fill the buffer. */
  139.   n = gs_canread(fp);
  140.   if (n < 0)
  141.     return n;
  142.   if (n < buflen) {
  143.     LOG(DBG_SYSCALL, "In gssock_read(%p, %p, %l): only %l bytes available",
  144.     (void *)fp, (void *)buf, buflen, n);
  145.     return E_NODATA;
  146.   }
  147.  
  148.   /* Okay, we can safely read. */
  149.   r = f_read(gs->sock_fd, buflen, buf);
  150.   if (r < 0) {
  151.     LOG(DBG_ERROR, "In gssock_read(%p, %p, %l): Fread() returns %e",
  152.     (void *)fp, (void *)buf, buflen, r);
  153.     return gs_xlate_error(r, "gssock_read");
  154.   } else {
  155.     /* Okay, according to the Fcntl(), we should have been able to fill the
  156.      * entire buffer; warn if we didn't. */
  157.     if (r < buflen)
  158.       LOG(DBG_ERROR, "In gssock_read(%p, %p, %l):  "
  159.       "only able to read %l of %l bytes",
  160.       (void *)fp, (void *)buf, buflen, r, buflen);
  161.     LOG(DBG_SYSCALL, "gssock_read(%p, %p, %l) reads %l bytes",
  162.     (void *)fp, (void *)buf, buflen, r);
  163.     return buflen;
  164.   }
  165. }
  166.  
  167. static long gssock_lseek(FILEPTR *fp, long where, short whence)
  168. {
  169.   /* MiNTnet sockets don't allow this, and STiK has no provisions for it;
  170.    * what're ya gonna do? ;) */
  171.   return E_NOROUTINE;
  172. }
  173.  
  174. static long gssock_ioctl(FILEPTR *fp, short cmd, void *buf)
  175. {
  176.   struct GS *gs = (struct GS *)fp->devinfo;
  177.  
  178.   switch (cmd) {
  179.     /* Most commands have args, and so get called via GLUESTIK_CMD. */
  180.     case GLUESTIK_CMD:
  181.       return gs_command(fp, (union GS_cmd *)buf);
  182.  
  183.     /* These commands have no args (or a simple arg passed via |buf|), and
  184.      * so can also be called directly. */
  185.     case CNBYTECOUNT_CMD:
  186.       return gs_canread(fp);
  187.     case CNGETNDB_CMD:
  188.       return gs_readndb(fp);
  189.     case CNGETINFO_CMD:
  190.       LOG(DBG_SYSCALL, "In gssock_ioctl(%p, CNGETINFO_CMD)", (void *)fp);
  191.       if (!gs) {
  192.     LOG(DBG_ERROR, "In gssock_ioctl(%p, CNGETINFO_CMD): bad handle",
  193.         (void *)fp);
  194.     return E_BADHANDLE;
  195.       }
  196.       LOG(DBG_SYSCALL, "gssock_ioctl(%p, CNGETINFO_CMD) returns %p",
  197.       (void *)fp, (void *)&(gs->cib));
  198.       return (long)&(gs->cib);
  199.     case GETERRTXT_CMD:
  200.       return (long)do_get_err_text((int16)(long)buf);
  201.     case GETDBGLVL_CMD:
  202.       return debug_level;
  203.     case SETDBGLVL_CMD:
  204.       debug_level = (long)buf;
  205.       return 0;
  206.  
  207.     /* Everything else gets passed through to the underlying socket. */
  208.     default:
  209.       if (gs->flags & GS_NOSOCKET) {
  210.     LOG(DBG_ERROR, "In gssock_ioctl(%p): bad handle", (void *)fp);
  211.     return E_BADHANDLE;
  212.       }
  213.       return f_cntl(gs->sock_fd, buf, cmd);
  214.   }
  215. }
  216.  
  217. static long gssock_datime(FILEPTR *fp, short *timeptr, short rwflag)
  218. {
  219.   struct GS *gs = (struct GS *)fp->devinfo;
  220.  
  221.   if (gs->flags & GS_NOSOCKET) {
  222.     LOG(DBG_ERROR, "In gssock_datime(%p, %p, %d): bad handle",
  223.     (void *)fp, (void *)timeptr, (int)rwflag);
  224.     return E_BADHANDLE;
  225.   }
  226.  
  227.   return f_datime(timeptr, gs->sock_fd, rwflag);
  228. }
  229.  
  230. static long gssock_close(FILEPTR *fp, short pid)
  231. {
  232.   struct GS *gs = (struct GS *)fp->devinfo;
  233.  
  234.   LOG(DBG_SYSCALL, "In gssock_close(%p)", (void *)fp);
  235.   gs_release(gs);
  236.   return 0;
  237. }
  238.  
  239. /* Fselect() should never be called on a GlueSTiK connection directly, but
  240.  * on the contained socket via TCP_wait_state() or similar. */
  241. static long gssock_select(FILEPTR *fp, long proc, short mode)
  242. {
  243.   return E_NOROUTINE;
  244. }
  245.  
  246. static void gssock_unselect(FILEPTR *fp, long proc, short mode)
  247. {
  248.   return;
  249. }
  250.  
  251. static long gs_command(FILEPTR *fp, union GS_cmd *args)
  252. {
  253.   struct GS *gs = (struct GS *)fp->devinfo;
  254.  
  255.   switch (args->cmd.cmd) {
  256.     case KRMALLOC_CMD:
  257.       return (long)gs_mem_alloc(args->KRmalloc_cmd.size);
  258.     case KRFREE_CMD:
  259.       gs_mem_free(args->KRfree_cmd.mem);
  260.       return 0;
  261.     case KRGETFREE_CMD:
  262.       return gs_mem_getfree(args->KRgetfree_cmd.flag);
  263.     case KRREALLOC_CMD:
  264.       return (long)gs_mem_realloc(args->KRrealloc_cmd.mem,
  265.                   args->KRrealloc_cmd.newsize);
  266.     case GETVSTR_CMD:
  267.       return (long)gs_getvstr(args->getvstr_cmd.var);
  268.     case TCP_OPEN_CMD:
  269.       return gs_connect(fp, args);
  270.     case TCP_WAIT_CMD:
  271.       return gs_wait(fp, args->TCP_wait_state_cmd.timeout);
  272.     case UDP_OPEN_CMD:
  273.       return gs_udp_open(fp, args);
  274.     case CNBYTECOUNT_CMD:
  275.       return gs_canread(fp);
  276.     case CNGETNDB_CMD:
  277.       return gs_readndb(fp);
  278.     case CNGETINFO_CMD:
  279.       if (!gs)
  280.     return E_BADHANDLE;
  281.       return (long)&(gs->cib);
  282.     case SETVSTR_CMD:
  283.       return gs_setvstr(args->setvstr_cmd.vs, args->setvstr_cmd.value);
  284.     case CNGETS_CMD:
  285.       return gs_read_delim(fp, args);
  286.     case GETERRTXT_CMD:
  287.       return (long)do_get_err_text(args->get_err_text_cmd.err);
  288.     case LOGENTRY_CMD:
  289.       if (args->log_entry_cmd.lev <= debug_level)
  290.     log_entry_raw(args->log_entry_cmd.pid, args->log_entry_cmd.lev,
  291.               args->log_entry_cmd.line);
  292.       return 0;
  293.     case GETDBGLVL_CMD:
  294.       return debug_level;
  295.     case SETDBGLVL_CMD:
  296.       debug_level = args->set_dbglvl_cmd.lev;
  297.       return 0;
  298.     default:
  299.       return E_PARAMETER;
  300.   }
  301. }